﻿using Microsoft.AspNetCore.Mvc;
using SD.Infrastructure.DTOBase;
using SD.Toolkits.AspNetCore.Attributes;
using SlamDunk.MES.IAppService.DTOs.Inputs;
using SlamDunk.MES.IAppService.DTOs.Outputs.DefinitionContext;
using SlamDunk.MES.IAppService.Interfaces;
using SlamDunk.ValueObjects.Enums;
using SlamDunk.ValueObjects.Structs;
using System;
using System.Collections.Generic;
using System.Linq;

namespace SlamDunk.MES.AppService.Host.Controllers
{
    /// <summary>
    /// 产品定义服务WebApi接口
    /// </summary>
    [ApiController]
    [Route("Api/[controller]/[action]")]
    public class DefinitionController : ControllerBase
    {
        #region # 字段及构造器

        /// <summary>
        /// 产品定义服务契约接口
        /// </summary>
        private readonly IDefinitionContract _definitionContract;

        /// <summary>
        /// 依赖注入构造器
        /// </summary>
        public DefinitionController(IDefinitionContract definitionContract)
        {
            this._definitionContract = definitionContract;
        }

        #endregion


        //命令部分

        #region # 创建物料清单 —— void CreateBom(string bomNo, string bomName...
        /// <summary>
        /// 创建物料清单
        /// </summary>
        /// <param name="bomNo">物料清单编号</param>
        /// <param name="bomName">物料清单名称</param>
        /// <param name="versionNo">版本号</param>
        /// <param name="productId">产品Id</param>
        /// <param name="runSize">运行规模</param>
        /// <param name="effectedDate">生效日期</param>
        /// <param name="expiredDate">失效日期</param>
        /// <param name="facilityId">工厂模型Id</param>
        /// <param name="description">描述</param>
        /// <param name="bomItemParams">物料清单项参数模型集</param>
        [HttpPost]
        [WrapPostParameters]
        public void CreateBom(string bomNo, string bomName, string versionNo, Guid productId, decimal runSize, DateTime? effectedDate, DateTime? expiredDate, Guid? facilityId, string description, IEnumerable<BomItemParam> bomItemParams)
        {
            this._definitionContract.CreateBom(bomNo, bomName, versionNo, productId, runSize, effectedDate, expiredDate, facilityId, description, bomItemParams);
        }
        #endregion

        #region # 修改物料清单 —— void UpdateBom(Guid bomId, string bomNo...
        /// <summary>
        /// 修改物料清单
        /// </summary>
        /// <param name="bomId">物料清单Id</param>
        /// <param name="bomNo">物料清单编号</param>
        /// <param name="bomName">物料清单名称</param>
        /// <param name="versionNo">版本号</param>
        /// <param name="productId">产品Id</param>
        /// <param name="runSize">运行规模</param>
        /// <param name="effectedDate">生效日期</param>
        /// <param name="expiredDate">失效日期</param>
        /// <param name="facilityId">工厂模型Id</param>
        /// <param name="description">描述</param>
        /// <param name="bomItemParams">物料清单项参数模型集</param>
        [HttpPost]
        [WrapPostParameters]
        public void UpdateBom(Guid bomId, string bomNo, string bomName, string versionNo, Guid productId, decimal runSize, DateTime? effectedDate, DateTime? expiredDate, Guid? facilityId, string description, IEnumerable<BomItemParam> bomItemParams)
        {
            this._definitionContract.UpdateBom(bomId, bomNo, bomName, versionNo, productId, runSize, effectedDate, expiredDate, facilityId, description, bomItemParams);
        }
        #endregion

        #region # 删除物料清单 —— void RemoveBom(Guid bomId)
        /// <summary>
        /// 删除物料清单
        /// </summary>
        /// <param name="bomId">物料清单Id</param>
        [HttpPost]
        [WrapPostParameters]
        public void RemoveBom(Guid bomId)
        {
            this._definitionContract.RemoveBom(bomId);
        }
        #endregion

        #region # 提交审核物料清单 —— void SubmitBom(Guid bomId)
        /// <summary>
        /// 提交审核物料清单
        /// </summary>
        /// <param name="bomId">物料清单Id</param>
        [HttpPost]
        [WrapPostParameters]
        public void SubmitBom(Guid bomId)
        {
            this._definitionContract.SubmitBom(bomId);
        }
        #endregion

        #region # 批量提交审核物料清单 —— void SubmitBoms(IEnumerable<Guid>...
        /// <summary>
        /// 批量提交审核物料清单
        /// </summary>
        /// <param name="bomIds">物料清单Id集</param>
        [HttpPost]
        [WrapPostParameters]
        public void SubmitBoms(IEnumerable<Guid> bomIds)
        {
            this._definitionContract.SubmitBoms(bomIds);
        }
        #endregion

        #region # 审核物料清单 —— void CheckBom(Guid bomId...
        /// <summary>
        /// 审核物料清单
        /// </summary>
        /// <param name="bomId">物料清单Id</param>
        /// <param name="passed">是否通过</param>
        /// <param name="checkedRemark">审核意见</param>
        [HttpPost]
        [WrapPostParameters]
        public void CheckBom(Guid bomId, bool passed, string checkedRemark)
        {
            this._definitionContract.CheckBom(bomId, passed, checkedRemark);
        }
        #endregion

        #region # 启用物料清单 —— void EnableBom(Guid bomId)
        /// <summary>
        /// 启用物料清单
        /// </summary>
        /// <param name="bomId">物料清单id</param>
        [HttpPost]
        [WrapPostParameters]
        public void EnableBom(Guid bomId)
        {
            this._definitionContract.EnableBom(bomId);
        }
        #endregion

        #region # 停用物料清单 —— void DisableBom(Guid bomId...
        /// <summary>
        /// 停用物料清单
        /// </summary>
        /// <param name="bomId">物料清单Id</param>
        /// <param name="reason">停用原因</param>
        [HttpPost]
        [WrapPostParameters]
        public void DisableBom(Guid bomId, string reason)
        {
            this._definitionContract.DisableBom(bomId, reason);
        }
        #endregion

        #region # 创建工艺类 —— void CreateProcessClass(string classNo, string className...
        /// <summary>
        /// 创建工艺类
        /// </summary>
        /// <param name="classNo">工艺类编号</param>
        /// <param name="className">工艺类名称</param>
        /// <param name="facilityId">工厂模型Id</param>
        /// <param name="description">描述</param>
        [HttpPost]
        [WrapPostParameters]
        public void CreateProcessClass(string classNo, string className, Guid? facilityId, string description)
        {
            this._definitionContract.CreateProcessClass(classNo, className, facilityId, description);
        }
        #endregion

        #region # 修改工艺类 —— void UpdateProcessClass(Guid processClassId, string classNo...
        /// <summary>
        /// 修改工艺类
        /// </summary>
        /// <param name="processClassId">工艺类Id</param>
        /// <param name="classNo">工艺类编号</param>
        /// <param name="className">工艺类名称</param>
        /// <param name="facilityId">工厂模型Id</param>
        /// <param name="description">描述</param>
        [HttpPost]
        [WrapPostParameters]
        public void UpdateProcessClass(Guid processClassId, string classNo, string className, Guid? facilityId, string description)
        {
            this._definitionContract.UpdateProcessClass(processClassId, classNo, className, facilityId, description);
        }
        #endregion

        #region # 删除工艺类 —— void RemoveProcessClass(Guid processClassId)
        /// <summary>
        /// 删除工艺类
        /// </summary>
        /// <param name="processClassId">工艺类Id</param>
        [HttpPost]
        [WrapPostParameters]
        public void RemoveProcessClass(Guid processClassId)
        {
            this._definitionContract.RemoveProcessClass(processClassId);
        }
        #endregion

        #region # 创建工艺 —— void CreateProcess(string processNo, string processName...
        /// <summary>
        /// 创建工艺
        /// </summary>
        /// <param name="processNo">工艺编号</param>
        /// <param name="processName">工艺名称</param>
        /// <param name="processClassId">工艺类Id</param>
        /// <param name="versionNo">版本号</param>
        /// <param name="productId">产品Id</param>
        /// <param name="runSize">运行规模</param>
        /// <param name="effectedDate">生效日期</param>
        /// <param name="expiredDate">失效日期</param>
        /// <param name="facilityId">工厂模型Id</param>
        /// <param name="description">描述</param>
        [HttpPost]
        [WrapPostParameters]
        public void CreateProcess(string processNo, string processName, Guid processClassId, string versionNo, Guid? productId, decimal runSize, Guid? facilityId, DateTime? effectedDate, DateTime? expiredDate, string description)
        {
            this._definitionContract.CreateProcess(processNo, processName, processClassId, versionNo, productId, runSize, facilityId, effectedDate, expiredDate, description);
        }
        #endregion

        #region # 修改工艺 —— void UpdateProcess(Guid processId, string processNo...
        /// <summary>
        /// 修改工艺
        /// </summary>
        /// <param name="processId">工艺Id</param>
        /// <param name="processNo">工艺编号</param>
        /// <param name="processName">工艺名称</param>
        /// <param name="processClassId">工艺类Id</param>
        /// <param name="versionNo">版本号</param>
        /// <param name="productId">产品Id</param>
        /// <param name="runSize">运行规模</param>
        /// <param name="effectedDate">生效日期</param>
        /// <param name="expiredDate">失效日期</param>
        /// <param name="facilityId">工厂模型Id</param>
        /// <param name="description">描述</param>
        [HttpPost]
        [WrapPostParameters]
        public void UpdateProcess(Guid processId, string processNo, string processName, Guid processClassId, string versionNo, Guid? productId, decimal runSize, Guid? facilityId, DateTime? effectedDate, DateTime? expiredDate, string description)
        {
            this._definitionContract.UpdateProcess(processId, processNo, processName, processClassId, versionNo, productId, runSize, facilityId, effectedDate, expiredDate, description);
        }
        #endregion

        #region # 删除工艺 —— void RemoveProcess(Guid processId)
        /// <summary>
        /// 删除工艺
        /// </summary>
        /// <param name="processId">工艺Id</param>
        [HttpPost]
        [WrapPostParameters]
        public void RemoveProcess(Guid processId)
        {
            this._definitionContract.RemoveProcess(processId);
        }
        #endregion

        #region # 创建工艺段 —— void CreateProcessSegment(Guid processId, string segmentNo...
        /// <summary>
        /// 创建工艺段
        /// </summary>
        /// <param name="processId">工艺Id</param>
        /// <param name="segmentNo">工艺段编号</param>
        /// <param name="segmentName">工艺段名称</param>
        /// <param name="durationQuota">工时定额</param>
        /// <param name="directivePath">工艺指导书</param>
        /// <param name="facilityId">工厂模型Id</param>
        /// <param name="workStationId">工位Id</param>
        /// <param name="formMode">表单模式</param>
        /// <param name="formDefinition">表单定义</param>
        /// <param name="needToInspect">是否需质检</param>
        /// <param name="sort">排序</param>
        /// <param name="description">描述</param>
        /// <param name="personRuleParams">工艺段人员规范参数模型集</param>
        /// <param name="equipmentRuleParams">工艺段设备规范参数模型集</param>
        /// <param name="materialRuleParams">工艺段物料规范参数模型集</param>
        /// <param name="parameterRuleParams">工艺段参数规范参数模型集</param>
        [HttpPost]
        [WrapPostParameters]
        public void CreateProcessSegment(Guid processId, string segmentNo, string segmentName, TimeSpan durationQuota, string directivePath, Guid? facilityId, Guid? workStationId, FormMode formMode, FormDefinition formDefinition, bool needToInspect, int sort, string description, [FromQuery] IEnumerable<SegmentPersonRuleParam> personRuleParams, [FromQuery] IEnumerable<SegmentEquipmentRuleParam> equipmentRuleParams, [FromQuery] IEnumerable<SegmentMaterialRuleParam> materialRuleParams, [FromQuery] IEnumerable<SegmentParameterRuleParam> parameterRuleParams)
        {
            this._definitionContract.CreateProcessSegment(processId, segmentNo, segmentName, durationQuota, directivePath, facilityId, workStationId, formMode, formDefinition, needToInspect, sort, description, personRuleParams, equipmentRuleParams, materialRuleParams, parameterRuleParams);
        }
        #endregion

        #region # 修改工艺段 —— void UpdateProcessSegment(Guid processId, Guid processSegmentId...
        /// <summary>
        /// 修改工艺段
        /// </summary>
        /// <param name="processId">工艺Id</param>
        /// <param name="processSegmentId">工艺段Id</param>
        /// <param name="segmentNo">工艺段编号</param>
        /// <param name="segmentName">工艺段名称</param>
        /// <param name="durationQuota">工时定额</param>
        /// <param name="directivePath">工艺指导书</param>
        /// <param name="facilityId">工厂模型Id</param>
        /// <param name="workStationId">工位Id</param>
        /// <param name="formMode">表单模式</param>
        /// <param name="formDefinition">表单定义</param>
        /// <param name="needToInspect">是否需质检</param>
        /// <param name="sort">排序</param>
        /// <param name="description">描述</param>
        /// <param name="personRuleParams">工艺段人员规范参数模型集</param>
        /// <param name="equipmentRuleParams">工艺段设备规范参数模型集</param>
        /// <param name="materialRuleParams">工艺段物料规范参数模型集</param>
        /// <param name="parameterRuleParams">工艺段参数规范参数模型集</param>
        [HttpPost]
        [WrapPostParameters]
        public void UpdateProcessSegment(Guid processId, Guid processSegmentId, string segmentNo, string segmentName, TimeSpan durationQuota, string directivePath, Guid? facilityId, Guid? workStationId, FormMode formMode, FormDefinition formDefinition, bool needToInspect, int sort, string description, [FromQuery] IEnumerable<SegmentPersonRuleParam> personRuleParams, [FromQuery] IEnumerable<SegmentEquipmentRuleParam> equipmentRuleParams, [FromQuery] IEnumerable<SegmentMaterialRuleParam> materialRuleParams, [FromQuery] IEnumerable<SegmentParameterRuleParam> parameterRuleParams)
        {
            this._definitionContract.UpdateProcessSegment(processId, processSegmentId, segmentNo, segmentName, durationQuota, directivePath, facilityId, workStationId, formMode, formDefinition, needToInspect, sort, description, personRuleParams, equipmentRuleParams, materialRuleParams, parameterRuleParams);
        }
        #endregion

        #region # 删除工艺段 —— void RemoveProcessSegment(Guid processId, Guid processSegmentId)
        /// <summary>
        /// 删除工艺段
        /// </summary>
        /// <param name="processId">工艺Id</param>
        /// <param name="processSegmentId">工艺段Id</param>
        [HttpPost]
        [WrapPostParameters]
        public void RemoveProcessSegment(Guid processId, Guid processSegmentId)
        {
            this._definitionContract.RemoveProcessSegment(processId, processSegmentId);
        }
        #endregion

        #region # 提交审核工艺 —— void SubmitProcess(Guid processId)
        /// <summary>
        /// 提交审核工艺
        /// </summary>
        /// <param name="processId">工艺Id</param>
        [HttpPost]
        [WrapPostParameters]
        public void SubmitProcess(Guid processId)
        {
            this._definitionContract.SubmitProcess(processId);
        }
        #endregion

        #region # 批量提交审核工艺 —— void SubmitProcesss(IEnumerable<Guid>...
        /// <summary>
        /// 批量提交审核工艺
        /// </summary>
        /// <param name="processIds">工艺Id集</param>
        [HttpPost]
        [WrapPostParameters]
        public void SubmitProcesses(IEnumerable<Guid> processIds)
        {
            this._definitionContract.SubmitProcesses(processIds);
        }
        #endregion

        #region # 审核工艺 —— void CheckProcess(Guid processId...
        /// <summary>
        /// 审核工艺
        /// </summary>
        /// <param name="processId">工艺Id</param>
        /// <param name="passed">是否通过</param>
        /// <param name="checkedRemark">审核意见</param>
        [HttpPost]
        [WrapPostParameters]
        public void CheckProcess(Guid processId, bool passed, string checkedRemark)
        {
            this._definitionContract.CheckProcess(processId, passed, checkedRemark);
        }
        #endregion

        #region # 启用工艺 —— void EnableProcess(Guid processId)
        /// <summary>
        /// 启用工艺
        /// </summary>
        /// <param name="processId">工艺id</param>
        [HttpPost]
        [WrapPostParameters]
        public void EnableProcess(Guid processId)
        {
            this._definitionContract.EnableProcess(processId);
        }
        #endregion

        #region # 停用工艺 —— void DisableProcess(Guid processId...
        /// <summary>
        /// 停用工艺
        /// </summary>
        /// <param name="processId">工艺Id</param>
        /// <param name="reason">停用原因</param>
        [HttpPost]
        [WrapPostParameters]
        public void DisableProcess(Guid processId, string reason)
        {
            this._definitionContract.DisableProcess(processId, reason);
        }
        #endregion


        //查询部分

        #region # 分页获取物料清单列表 —— PageModel<BomInfo> GetBomsByPage(string keywords...
        /// <summary>
        /// 分页获取物料清单列表
        /// </summary>
        /// <param name="keywords">关键字</param>
        /// <param name="productId">产品Id</param>
        /// <param name="facilityId">工厂模型Id</param>
        /// <param name="enabled">是否启用</param>
        /// <param name="checkStatus">审核状态</param>
        /// <param name="pageIndex">页码</param>
        /// <param name="pageSize">页容量</param>
        /// <returns>物料清单列表</returns>
        [HttpGet]
        public PageModel<BomInfo> GetBomsByPage(string keywords, Guid? productId, Guid? facilityId, bool? enabled, CheckStatus? checkStatus, int pageIndex, int pageSize)
        {
            return this._definitionContract.GetBomsByPage(keywords, productId, facilityId, enabled, checkStatus, pageIndex, pageSize);
        }
        #endregion

        #region # 获取物料清单项列表 —— IEnumerable<BomItemInfo> GetBomItems(Guid bomId)
        /// <summary>
        /// 获取物料清单项列表
        /// </summary>
        /// <param name="bomId">物料清单Id</param>
        /// <returns>物料清单项列表</returns>
        [HttpGet]
        public IEnumerable<BomItemInfo> GetBomItems(Guid bomId)
        {
            return this._definitionContract.GetBomItems(bomId).OrderBy(x => x.Sort);
        }
        #endregion

        #region # 计算物料需求 —— IDictionary<Guid, decimal> CalculateMaterialAsks(Guid bomId...
        /// <summary>
        /// 计算物料需求
        /// </summary>
        /// <param name="bomId">物料清单Id</param>
        /// <param name="runSize">运行规模</param>
        /// <returns>物料需求字典</returns>
        [HttpGet]
        public IDictionary<Guid, decimal> CalculateMaterialAsks(Guid bomId, decimal runSize)
        {
            return this._definitionContract.CalculateMaterialAsks(bomId, runSize);
        }
        #endregion

        #region # 分页获取工艺类列表 —— PageModel<ProcessClassInfo> GetProcessClassesByPage(string keywords...
        /// <summary>
        /// 分页获取工艺类列表
        /// </summary>
        /// <param name="keywords">关键字</param>
        /// <param name="facilityId">工厂模型Id</param>
        /// <param name="pageIndex">页码</param>
        /// <param name="pageSize">页容量</param>
        /// <returns>工艺类列表</returns>
        [HttpGet]
        public PageModel<ProcessClassInfo> GetProcessClassesByPage(string keywords, Guid? facilityId, int pageIndex, int pageSize)
        {
            return this._definitionContract.GetProcessClassesByPage(keywords, facilityId, pageIndex, pageSize);
        }
        #endregion

        #region # 分页获取工艺列表 —— PageModel<ProcessInfo> GetProcessesByPage(string keywords...
        /// <summary>
        /// 分页获取工艺列表
        /// </summary>
        /// <param name="keywords">关键字</param>
        /// <param name="processClassId">工艺类Id</param>
        /// <param name="productId">产品Id</param>
        /// <param name="facilityId">工厂模型Id</param>
        /// <param name="enabled">是否启用</param>
        /// <param name="checkStatus">审核状态</param>
        /// <param name="pageIndex">页码</param>
        /// <param name="pageSize">页容量</param>
        /// <returns>工艺列表</returns>
        [HttpGet]
        public PageModel<ProcessInfo> GetProcessesByPage(string keywords, Guid? processClassId, Guid? productId, Guid? facilityId, bool? enabled, CheckStatus? checkStatus, int pageIndex, int pageSize)
        {
            return this._definitionContract.GetProcessesByPage(keywords, processClassId, productId, facilityId, enabled, checkStatus, pageIndex, pageSize);
        }
        #endregion

        #region # 获取工艺/工艺段字典 —— IDictionary<Process, ProcessSegment[]> GetProcessesWithSegments()
        /// <summary>
        /// 获取工艺/工艺段字典
        /// </summary>
        /// <returns>工艺/工艺段字典</returns>
        [HttpGet]
        public IEnumerable<KeyValuePair<ProcessInfo, ProcessSegmentInfo[]>> GetProcessesWithSegments()
        {
            IDictionary<ProcessInfo, ProcessSegmentInfo[]> dictionary = this._definitionContract.GetProcessesWithSegments();

            IList<KeyValuePair<ProcessInfo, ProcessSegmentInfo[]>> keyValuePairs = new List<KeyValuePair<ProcessInfo, ProcessSegmentInfo[]>>();
            foreach (KeyValuePair<ProcessInfo, ProcessSegmentInfo[]> kv in dictionary)
            {
                keyValuePairs.Add(new KeyValuePair<ProcessInfo, ProcessSegmentInfo[]>(kv.Key, kv.Value));
            }

            return keyValuePairs;
        }
        #endregion

        #region # 获取工艺段列表 —— IEnumerable<ProcessSegmentInfo> GetProcessSegments(Guid processId)
        /// <summary>
        /// 获取工艺段列表
        /// </summary>
        /// <param name="processId">工艺Id</param>
        /// <returns>工艺段列表</returns>
        [HttpGet]
        public IEnumerable<ProcessSegmentInfo> GetProcessSegments(Guid processId)
        {
            return this._definitionContract.GetProcessSegments(processId).OrderBy(x => x.Sort);
        }
        #endregion

        #region # 获取工艺段人员规范列表 —— IEnumerable<SegmentPersonRuleInfo> GetProcessSegmentPersonRules(...
        /// <summary>
        /// 获取工艺段人员规范列表
        /// </summary>
        /// <param name="processSegmentId">工艺段Id</param>
        /// <returns>工艺段人员规范列表</returns>
        [HttpGet]
        public IEnumerable<SegmentPersonRuleInfo> GetProcessSegmentPersonRules(Guid processSegmentId)
        {
            return this._definitionContract.GetProcessSegmentPersonRules(processSegmentId);
        }
        #endregion

        #region # 获取工艺段设备规范列表 —— IEnumerable<SegmentEquipmentRuleInfo> GetProcessSegmentEquipmentRules(...
        /// <summary>
        /// 获取工艺段设备规范列表
        /// </summary>
        /// <param name="processSegmentId">工艺段Id</param>
        /// <returns>工艺段设备规范列表</returns>
        [HttpGet]
        public IEnumerable<SegmentEquipmentRuleInfo> GetProcessSegmentEquipmentRules(Guid processSegmentId)
        {
            return this._definitionContract.GetProcessSegmentEquipmentRules(processSegmentId);
        }
        #endregion

        #region # 获取工艺段物料规范列表 —— IEnumerable<SegmentMaterialRuleInfo> GetProcessSegmentMaterialRules(...
        /// <summary>
        /// 获取工艺段物料规范列表
        /// </summary>
        /// <param name="processSegmentId">工艺段Id</param>
        /// <returns>工艺段物料规范列表</returns>
        [HttpGet]
        public IEnumerable<SegmentMaterialRuleInfo> GetProcessSegmentMaterialRules(Guid processSegmentId)
        {
            return this._definitionContract.GetProcessSegmentMaterialRules(processSegmentId);
        }
        #endregion

        #region # 获取工艺段参数规范列表 —— IEnumerable<SegmentParameterRuleInfo> GetProcessSegmentParameterRules(...
        /// <summary>
        /// 获取工艺段参数规范列表
        /// </summary>
        /// <param name="processSegmentId">工艺段Id</param>
        /// <returns>工艺段参数规范列表</returns>
        [HttpGet]
        public IEnumerable<SegmentParameterRuleInfo> GetProcessSegmentParameterRules(Guid processSegmentId)
        {
            return this._definitionContract.GetProcessSegmentParameterRules(processSegmentId);
        }
        #endregion
    }
}
